package magneticCave;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.*;
import javax.swing.border.LineBorder;

public class BoardImpl extends JFrame implements ActionListener, MouseListener
{

	private JMenuBar jmb;
	private JMenu menuGame;
//	private MenuItem item1, item2;
	private JMenuItem menuExit;
	private JMenu menuStart; //secondary menu
	private JMenuItem itemA,itemB,itemC;
	
	private static final int CELLS_ACROSS = 8;
	private static final int CELLS_DOWN = 8;
	
	private static final int HUMAN_V_COMP = 1;
	private static final int HUMAN_V_HUMAN = 2;

	
	
	private int whoseTurn = Leaf.NO_ONE;
	private int compPlayer = Leaf.NO_ONE; //which player is the computer? 
	private int gameMode = 0;
//	private Cell[][]cells = new Cell[8][8]; //cells representing the graphical view of the grid
	private Cell[][]cells = null;
	private int[] grid = new int[CELLS_ACROSS * CELLS_DOWN]; //actual Grid
	
	private JLabel labelBegin = new JLabel("Black: 0 and White: 0");
	private JLabel labelNorth = new JLabel("          A               B                C                D                E                  F" +
			"                G                  H");
	private JLabel labelWest1 = new JLabel("<html>8<br><br><br>7<br><br><br>6<br><br><br>5<br><br><br>4<br><br><br>3<br><br><br>2<br><br><br>1");
    private JButton jb1 = new JButton("Game Start");
	
	private JPanel panelBoard = new JPanel(new GridLayout(8,8));
//	private JPanel panel2 = new JPanel();
	private JPanel panel3= new JPanel();
	private JPanel panelMenu= new JPanel(new BorderLayout());
	int black_count = 0;
	int white_count = 0;
	
	public BoardImpl()
	{
		init();
	}
	
	
	public void init()
	{
		jmb = new JMenuBar();
		menuGame = new JMenu("Game");
		
		menuStart = new JMenu("Game Start");
		menuExit = new JMenuItem("Game Exit");
		itemA = new JMenuItem("Human vs Human");
		itemB = new JMenuItem("Human vs Computer"); //Human takes the first action with Black piece
		itemC = new JMenuItem("Computer vs Human");//Computer takes the first action with Black piece
		
		menuStart.add(itemA);
		menuStart.add(itemB);
		menuStart.add(itemC);
		
		menuGame.add(menuStart);
		menuGame.addSeparator();
		menuGame.add(menuExit);
		
		jmb.add(menuGame);
		
		itemA.addActionListener(this);
		itemA.setActionCommand("Human vs Human");
		itemB.addActionListener(this);
		itemB.setActionCommand("Human vs Computer");
		itemC.addActionListener(this);
		itemC.setActionCommand("Computer vs Human");
		
//		this.setLayout(new GridLayout(2,2));
		this.setSize(500,500);
		this.setLocation(300, 100);
		this.setTitle("Magnetic Cave");
		this.setBackground(Color.DARK_GRAY);		
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		
		panelMenu.add(jmb,BorderLayout.NORTH);
		panelMenu.add(labelNorth,BorderLayout.WEST);
		panel3.add(labelWest1);
		getContentPane().add(panel3,BorderLayout.EAST);
		getContentPane().add(labelBegin,BorderLayout.SOUTH);
		getContentPane().add(panelMenu,BorderLayout.NORTH);
		
		addMouseListener(this);
		
		setVisible(true);
		
		//DoCompVComp();
	}
		
		// inner class Cell
		

		
		
	
	
	public static void main(String[] args) 
	{
		BoardImpl frame = new BoardImpl();
	}


	@Override
	public void actionPerformed(ActionEvent e) 
	{
		// TODO Auto-generated method stub

		if(e.getActionCommand().equals("Human vs Human"))
		{
//			System.out.println("A");
			gameMode = HUMAN_V_HUMAN;
			whoseTurn = Leaf.BLACK;
			SetupBoard();
		}
		else if(e.getActionCommand().equals("Human vs Computer"))
		{
			gameMode = HUMAN_V_COMP;
			compPlayer = Leaf.WHITE;
			whoseTurn = Leaf.BLACK;
			SetupBoard();
		//	System.out.println("B");
		}
		else if(e.getActionCommand().equals("Computer vs Human"))
		{
		//	System.out.println("C");
			gameMode = HUMAN_V_COMP;
			compPlayer = Leaf.BLACK;
			whoseTurn = Leaf.BLACK;
			SetupBoard();
			//Computer goes first
			DoCompMove();
		}		
	}
	
	public void SetupBoard()
	{
		panelBoard.removeAll();
		cells = new Cell[8][8];
		whoseTurn = Leaf.BLACK;
		for(int i = 0; i<8; i++)
		{
			for(int j = 0; j<8; j++)
			{
				panelBoard.add(cells[i][j] = new Cell());
				cells[i][j].setToken(Leaf.NO_ONE);
				grid[(i * Leaf.ROWS)+ j ] = 0;
			}
		}
		
		String playerName = (whoseTurn == Leaf.BLACK) ? "Black" : "White";
		labelBegin.setText(playerName + "'s turn Black: " + black_count + " White: " + white_count);
		
		getContentPane().add(panelBoard,BorderLayout.CENTER);
		this.setVisible(true);
		
	}  
	
	public void DoCompMove()
	{ 
		//generate a tree given the current board state.
		
		
		int[] copyGrid = grid.clone();
		Leaf tree = Globals.GenerateTree(4, copyGrid, whoseTurn);
		//do the move that is recommended
		int bestX = tree.GetBestMoveCol();
		int bestY = tree.GetBestMoveRow();
		System.out.println(returnCoordinates(bestX, bestY));
		MakeMove(bestY, bestX);
		
	
	//	whoseTurn = whoseTurn == Leaf.BLACK ? Leaf.WHITE : Leaf.BLACK;
	}
	
	 public String returnCoordinates(int x, int y)
	 {
		  String moveInfor = null;
		  if(whoseTurn == Leaf.BLACK)
		  {
			  moveInfor = "The coordinates of the Black move are col: "+x+",row:"+y;
		  }
		  else if(whoseTurn == Leaf.WHITE)
		  {
			  moveInfor = "The coordinates of the White move are col: "+x+",row: "+y;
		  }
	  
	     return moveInfor;
	  
	 }
	@Override
	public void mouseClicked(MouseEvent e) 
	{
		if(whoseTurn == compPlayer)
			return;
		
		int button = e.getButton(); //stop right-clicks from doing anything
		if(e.getButton() == MouseEvent.BUTTON3)
		{
			labelBegin.setText("Value: " + Globals.Evaluate(grid, whoseTurn));
			return;
		}
		
		if(whoseTurn != Leaf.NO_ONE)
		{
			int cellWidth = cells[0][0].getWidth();
			int cellHeight = cells[0][0].getHeight();
			
			//get mouse Pos relative to topleft cell
			int pX = e.getX() - cells[0][0].getX();
			int pY = e.getY() - cells[0][0].getY() - 70; //offset for menu and such
			//make sure the clicking happened within the bounds of the squares
			if(pX < cells[0][0].getX() || pY < cells[0][0].getY() ||
			   pX > cells[CELLS_ACROSS-1][CELLS_DOWN-1].getX() + cells[CELLS_ACROSS-1][CELLS_DOWN-1].getWidth() || 
			    pY > cells[CELLS_ACROSS-1][CELLS_DOWN-1].getY() + cells[CELLS_ACROSS-1][CELLS_DOWN-1].getHeight())
				return;
	

			//if we land exactly between 2 cells, don't make a move, because its too ambiguous
			if(pX % cellWidth == 0) {				
				return;
			}
		    if(pY % cellHeight == 0){
				return;		    	
		    }
		   
		    int col = pX/cellWidth;
			int row = pY/cellHeight;	
		
			//bounds checking
			if(col < 0)
				col = 0;
			else if(col > CELLS_ACROSS -1)
				col = CELLS_ACROSS - 1;
			if (row < 0)
				row = 0;
			else if(row > CELLS_DOWN-1)
				row = CELLS_DOWN - 1;
			
			
		    //MakeMove(row, col);
			
			if(MakeMove(row, col) && whoseTurn != Leaf.NO_ONE && gameMode == HUMAN_V_COMP)
				DoCompMove();
			
		}
	}

	public boolean MakeMove(int row, int col)
	{
		//can we make a move? If so, place something down
		if(Globals.MakeMove(grid, row, col, whoseTurn ))
		{
			cells[row][col].setToken(whoseTurn);
			
			//increment how many pieces of each color are on the board
			if(whoseTurn == Leaf.BLACK)
			{
				black_count++;	    				
			}
			else if(whoseTurn == Leaf.WHITE)
			{
				white_count++;
			}
			
			
			int winner = Globals.CheckForWinner(grid);
			if(winner == Leaf.BLACK)
			{
				labelBegin.setText("Black wins! Black: " + black_count + " White: " + white_count);
				whoseTurn = Leaf.NO_ONE;
			}
			else if(winner == Leaf.WHITE)
			{
				labelBegin.setText("White wins! Black: " + black_count + " White: " + white_count);
				whoseTurn = Leaf.NO_ONE;
			}
			else
			{
				whoseTurn = (whoseTurn == Leaf.BLACK) ? Leaf.WHITE : Leaf.BLACK;
				String playerName = (whoseTurn == Leaf.BLACK) ? "Black" : "White";
				labelBegin.setText(playerName + "'s turn Black: " + black_count + " White: " + white_count);
			}	
			return true;
			
		}
		else
		{
			labelBegin.setText("Illegal move, try again");
			return false;
		}
	}
	
	
	public void DoCompVComp()
	{
		Leaf tree = Globals.GenerateTree(3, new int[8*8], Leaf.BLACK);
		
		BufferedWriter writer = null;
		try{
		writer = new BufferedWriter(new FileWriter("output.txt"));
	
		}catch(IOException e)
		{
			System.out.println("Was unable to open file output.txt for writing");
		}
		
		
	//	MinimaxSearcher ms = new MinimaxSearcher();
	//	ms.eval(tree);
		
	//	System.out.println("The value of best move is "+ms.getBestMove());
	//	System.out.println("The value of the count is "+ms.getNodeCount());
		
//		try{
	//	writer.write("The value of best move is " + ms.getBestMove() + "\n");
	//	writer.write("The value of the count is "+ms.getNodeCount() + "\n");
//		}
//		catch(IOException e)
//		{
//			System.out.println("Error writing the last 2 lines of output to the file.");
//		}
		tree.Report(writer);
		
		if(writer != null)
		{
			System.out.println("Full output can be read in output.txt. It is recommended to use notepad++ or similar program for maximum readability");
			try{
			writer.close();
			}
			catch(IOException e)
			{
				e.printStackTrace();
			}
		}
	}
	
	
	
	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	
}
